#define NO_ZLIB MYNAME ": No zlib support.\n"
/* About the ZLIB_INHIBITED stuff:
- *
+ *
* If a user goes out of his way to build with ZLIB_INHIBITED set,
* we jettison our use of zlib entirely within this file, replacing
* all calls out to zlib with calls to abort() as that's an internal
self->handle.gz = gzopen(self->name, openmode);
if (self->handle.gz == NULL) {
- fatal("%s: Cannot %s file '%s'!\n",
- self->module,
+ fatal("%s: Cannot %s file '%s'!\n",
+ self->module,
(self->mode == 'r') ? "open" : "create",
self->name);
}
int result = 0;
char *target = buf;
int count = size * members;
-
+
if (self->back != -1) {
*target++ = self->back;
count--;
self->back = -1;
}
result += gzread(self->handle.gz, target, count);
-
+
/* Check for an incomplete READ */
if ((members == 1) && (size > 1) && (result > 0) && (result < (int)size))
fatal("%s: Unexpected end of file (EOF)!\n", self->module);
if ((result < 0) || ((gbsize_t)result < members)) {
int errnum;
const char *errtxt;
-
+
errtxt = gzerror(self->handle.gz, &errnum);
-
+
/* Workaround for zlib bug: buffer error on empty files */
if ((errnum == Z_BUF_ERROR) && (gztell(self->handle.gz) == 0)) {
return (gbsize_t) 0;
gzapi_eof(gbfile *self)
{
int res = 0;
-
+
if (self->back != -1) return res;
res = gzeof(self->handle.gz);
{
int result;
gbsize_t pos = 0;
-
+
if (whence != SEEK_SET) pos = ftell(self->handle.std);
result = fseek(self->handle.std, offset, whence);
{
int errno;
gbsize_t result = fread(buf, size, members, self->handle.std);
-
+
if ((result < members) && (errno = ferror(self->handle.std))) {
fatal("%s: Error %d occured during read of file '%s'!\n",
self->module, errno, self->name);
memapi_seek(gbfile *self, gbint32 offset, int whence)
{
long long pos = (int)self->mempos;
-
+
switch (whence) {
case SEEK_CUR:
case SEEK_END: pos = pos + offset; break;
}
if ((pos < 0) || (pos > self->memlen)) return -1;
-
+
self->mempos = pos;
return 0;
}
memapi_write(const void *buf, const gbsize_t size, const gbsize_t members, gbfile *self)
{
gbsize_t count;
-
+
if ((size == 0) && (members == 0)) { /* truncate stream */
self->memlen = self->mempos;
return 0;
}
-
+
count = size * members;
-
+
if (self->mempos + count > self->memsz) {
self->memsz = ((self->mempos + count + 4095) / 4096) * 4096;
self->handle.mem = xrealloc(self->handle.mem, self->memsz);
return;
}
-static int
+static int
memapi_error(gbfile *self)
{
return 0;
}
-
+
/* GPSBabel 'file' standard calls */
/*
gbfile *file;
const char *m;
int len;
-
+
file = xcalloc(1, sizeof(*file));
-
+
file->module = xstrdup(module);
file->mode = 'r'; // default
file->binary = (strchr(mode, 'b') != NULL);
file->back = -1;
file->memapi = (filename == NULL);
-
+
for (m = mode; *m; m++) {
switch(tolower(*m)) {
case 'r':
else {
file->name = xstrdup(filename);
file->is_pipe = (strcmp(filename, "-") == 0);
-
+
/* Do we have a '.gz' extension in the filename ? */
len = strlen(file->name);
if ((len > 3) && (case_ignore_strcmp(&file->name[len-3], ".gz") == 0)) {
if (file->gzapi) {
#if !ZLIB_INHIBITED
-
+
file->fileclearerr = gzapi_clearerr;
file->fileclose = gzapi_close;
file->fileeof = gzapi_eof;
return file;
}
-/*
- * gbfopen_be: as gbfopen, but set the BIG-ENDIAN flag
+/*
+ * gbfopen_be: as gbfopen, but set the BIG-ENDIAN flag
*/
gbfile *
gbfopen_be(const char *filename, const char *mode, const char *module)
{
gbfile *result;
-
+
result = gbfopen(filename, mode, module);
result->big_endian = 1;
-
+
return result;
}
/*
* gbfclose: (as fclose)
*/
-
+
void
gbfclose(gbfile *file)
{
if (!file) return;
-
+
file->fileclose(file);
xfree(file->name);
/*
* gbfgetc: (as fgetc)
*/
-
-int
+
+int
gbfgetc(gbfile *file)
{
unsigned char c;
/*
* gbfgets: (as fgets)
*/
-
-char *
+
+char *
gbfgets(char *buf, int len, gbfile *file)
{
char *result = buf;
-
+
while (--len > 0) {
int c = gbfgetc(file);
if (c == EOF) break;
-
+
*(unsigned char *)buf = (unsigned char)c;
buf++;
-
+
if (c == '\r') {
c = gbfgetc(file);
if ((c != '\n') && (c != EOF)) gbfungetc(c, file);
/*
* gbfread: (as fread)
*/
-
+
gbsize_t
gbfread(void *buf, const gbsize_t size, const gbsize_t members, gbfile *file)
{
/*
* gbvfprintf: (as vfprintf)
*/
-
+
int gbvfprintf(gbfile *file, const char *format, va_list ap)
{
int len;
-
+
for (;;) {
va_list args;
-
+
va_copy(args, ap);
len = vsnprintf(file->buff, file->buffsz, format, args);
va_end(args);
/* First case: C99 behaviour. Len is correctly sized.
* add space for null terminator. Next time through the
* loop we're guaranteed success.
- *
+ *
* Second case: SUS (and Windows) behaviour. We know it
* doesn't fit, but we don't know how big it has to be.
` * double it and try again. We'll loop until we succeed.
* Since we keep the I/O buffer in the file handle, we
* quickly reach a steady state on the size of these buffers.
*/
- if (len > -1)
+ if (len > -1)
file->buffsz = len + 1;
- else
+ else
file->buffsz *= 2;
file->buff = xrealloc(file->buff, file->buffsz);
/*
* gbfprintf: (as fprintf)
*/
-
-int
+
+int
gbfprintf(gbfile *file, const char *format, ...)
{
va_list args;
int result;
-
+
va_start(args, format);
result = gbvfprintf(file, format, args);
va_end(args);
-
+
return result;
}
/*
* gbfputc: (as fputc)
*/
-
-int
+
+int
gbfputc(int c, gbfile *file)
{
unsigned char temp = (unsigned int) c;
-
+
gbfwrite(&temp, 1, 1, file);
-
+
return c;
}
* gbfputs: (as fputs)
*/
-int
+int
gbfputs(const char *s, gbfile *file)
{
return gbfwrite(s, 1, strlen(s), file);
* gbfwrite: (as fwrite)
*/
-int
+int
gbfwrite(const void *buf, const gbsize_t size, const gbsize_t members, gbfile *file)
{
int result;
-
+
result = file->filewrite(buf, size, members, file);
if (result != members) {
- fatal("%s: Could not write %lld bytes to %s (result %d)!\n",
+ fatal("%s: Could not write %lld bytes to %s (result %d)!\n",
file->module,
(long long int) (members - result) * size,
file->name,
result);
}
-
+
return result;
}
/*
* gbfflush: (as fflush)
*/
-
+
int
gbfflush(gbfile *file)
{
/*
* gbferror: (as ferror)
*/
-
+
int
gbferror(gbfile *file)
{
/*
* gbfrewind: (as frewind)
*/
-
+
void
gbfrewind(gbfile *file)
{
/*
* gbfseek: (as fseek)
*/
-
+
int
gbfseek(gbfile *file, gbint32 offset, int whence)
{
* gbftell: (as ftell)
*/
-gbsize_t
+gbsize_t
gbftell(gbfile *file)
{
gbsize_t result = file->filetell(file);
* gbfeof: (as feof)
*/
-int
+int
gbfeof(gbfile *file)
{
return file->fileeof(file);
gbfgetint32(gbfile *file)
{
char buf[4];
-
+
is_fatal((gbfread(&buf, 1, sizeof(buf), file) != sizeof(buf)),
"%s: Unexpected end of file (%s)!\n", file->module, file->name);
gbfgetint16(gbfile *file)
{
char buf[2];
-
+
is_fatal((gbfread(&buf, 1, sizeof(buf), file) != sizeof(buf)),
"%s: Unexpected end of file (%s)!\n", file->module, file->name);
-
+
if (file->big_endian)
return be_read16(buf);
else
* gbfgetdbl: read a double value (8 byte, double precision) from input stream
*/
-double
+double
gbfgetdbl(gbfile *file)
{
char buf[8];
gbfgetflt(gbfile *file)
{
char buf[4];
-
+
is_fatal((gbfread(&buf, 1, sizeof(buf), file) != sizeof(buf)),
"%s: Unexpected end of file (%s)!\n", file->module, file->name);
* gbfgetcstr: Reads a string from file until either a '\0' or eof.
* The result is a temporary allocated entity: use it or free it!
*/
-
+
char *
gbfgetcstr(gbfile *file)
{
char *result;
int len = 0;
char *str = file->buff;
-
+
for (;;) {
int c = gbfgetc(file);
-
+
if ((c == 0) || (c == EOF)) break;
-
+
if (len == file->buffsz) {
file->buffsz += 64;
str = file->buff = xrealloc(file->buff, file->buffsz + 1);
str[len] = c;
len++;
}
-
+
result = (char *) xmalloc(len + 1);
if (len > 0)
memcpy(result, str, len);
result[len] = '\0';
-
+
return result;
}
{
int len;
char *result;
-
+
len = gbfgetc(file);
result = xmalloc(len + 1);
if (len > 0) {
gbfread(result, 1, len, file);
}
result[len] = '\0';
-
+
return result;
}
{
int len = 0;
char *result = file->buff;
-
+
for (;;) {
char buff[8];
int clen;
- int c = gbfgetc(file);
+ int c0, c1;
- if ((c == EOF) && (len == 0)) return NULL;
-
- c = c | (gbfgetc(file) << 8);
- if (file->big_endian) c = be_read16(&c);
+ c0 = gbfgetc(file);
+ if ((c0 == EOF) && (len == 0)) return NULL;
+ c1 = gbfgetc(file);
+ if ((c1 == EOF) && (len == 0)) return NULL;
- if (c == '\r') {
- c = gbfgetc(file) | (gbfgetc(file) << 8);
- if (file->big_endian) c = be_read16(&c);
- if (c != '\n')
- fatal("%s: Invalid unicode (UCS-2/%s endian) line break!\n",
+ if (file->big_endian) c0 = c1 | (c0 << 8);
+ else c0 = c0 | (c1 << 8);
+
+ if (c0 == '\r') {
+
+ c0 = gbfgetc(file);
+ if ((c0 == EOF) && (len == 0)) return NULL;
+ c1 = gbfgetc(file);
+ if ((c1 == EOF) && (len == 0)) return NULL;
+
+ if (file->big_endian) c0 = c1 | (c0 << 8);
+ else c0 = c0 | (c1 << 8);
+
+ if (c0 != '\n')
+ fatal("%s: Invalid unicode (UCS-2/%s endian) line break!\n",
file->module,
file->big_endian ? "Big" : "Little");
break;
}
-
- clen = cet_ucs4_to_utf8(buff, sizeof(buff), c);
+
+ clen = cet_ucs4_to_utf8(buff, sizeof(buff), c0);
if (len+clen >= file->buffsz) {
file->buffsz += 64;
len += clen;
}
result[len] = '\0'; // terminate resulting string
-
+
return result;
}
{
int len = 0;
char *result = file->buff;
-
+
if (file->unicode) return gbfgetucs2str(file);
-
+
for (;;) {
int c = gbfgetc(file);
-
+
if ((c == EOF) || (c == 0x1A)) {
if (len == 0) {
return NULL;
else gbfungetc(c1, file);
}
}
-
+
file->unicode_checked = 1;
-
+
if (len == file->buffsz) {
file->buffsz += 64;
result = file->buff = xrealloc(file->buff, file->buffsz + 1);
len++;
}
result[len] = '\0'; // terminate resulting string
-
+
return result;
}
/*
* gbfputint16: write a signed 16-bit integer value into output stream
*/
-
+
int
gbfputint16(const gbint16 i, gbfile *file)
{
char buf[2];
-
+
if (file->big_endian)
be_write16(buf, i);
else
gbfputint32(const gbint32 i, gbfile *file)
{
char buf[4];
-
+
if (file->big_endian)
be_write32(buf, i);
else
gbfputdbl(const double d, gbfile *file)
{
char buf[8];
-
+
endian_write_double(buf, d, ! file->big_endian);
return gbfwrite(buf, 1, sizeof(buf), file);
}
* gbfputflt: write a float value (4 byte, single precision) into output stream
*/
-int
+int
gbfputflt(const float f, gbfile *file)
{
char buf[4];
-
+
endian_write_float(buf, f, ! file->big_endian);
return gbfwrite(buf, 1, sizeof(buf), file);
}
* return the number of written characters
*/
-int
+int
gbfputcstr(const char *s, gbfile *file)
{
int len;
-
+
len = (s == NULL) ? 0 : strlen(s);
if (len > 0) {
return gbfwrite(s, 1, len + 1, file);
gbfputpstr(const char *s, gbfile *file)
{
int len;
-
+
len = (s == NULL) ? 0 : strlen(s);
if (len > 255) len = 255; /* the maximum size of a standard pascal string */
gbfputc(len, file);